package com.example.ui.util;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.ui.dto.OpenAiRes;
import com.example.ui.dto.OpenAiResp;
import com.example.ui.dto.TranExcel;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author yliu
 */
public class OpenUtils {

    public final static String TRAN_FILE = "tran";

    public final static String DISEASE_NAME = "脑肿瘤服务项目";

    public final static String EMPI_ID_EXCEL_FILE_PATH = "C:\\Users\\yliu\\Downloads\\query-hive-49965.xlsx";

    public final static String SQL_FILE_PATH = "C:\\Users\\yliu\\Desktop\\trans\\" + DISEASE_NAME + ".csv";

    public final static String BASE_PATH = "D:\\TextAnalytics\\" + DISEASE_NAME + "\\";

    public static int corePoolSize = Runtime.getRuntime().availableProcessors();
    public static int maximumPoolSize = corePoolSize * 2;
    public static long keepAliveTime = 60L;
    public static TimeUnit timeUnit = TimeUnit.SECONDS;

    public static ExecutorService executor = new ThreadPoolExecutor(
            corePoolSize,
            maximumPoolSize,
            keepAliveTime,
            timeUnit,
            new LinkedBlockingQueue<>(),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.CallerRunsPolicy()
    );

    public static void main(String[] args) {
        //1、读取病种和患者对应excel文件，拼接sql查询数据库录音转文字记录
//        readEmpiIdToSql();

//        //2、读取数据库导出csv文件，筛选出患者文字
        readTransText();
//        //3、利用gpt统计出患者问题
        readPatCallText();
        try {
            // 等待线程池中的所有线程执行完毕，或者设置一个合理的超时时间
            boolean terminated = executor.awaitTermination(5, TimeUnit.MINUTES);
            if (terminated) {
                //4、总结高频问题，计算问题出现概率
                readDiseaseTxtToHighProblems();
//        5、去重
                distinct();
            } else {
                // 超时，线程池中的某些线程可能仍在执行
                System.out.println("Timeout while waiting for threads to complete.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //4、总结高频问题，计算问题出现概率
//        readDiseaseTxtToHighProblems();
//////        5、去重
//        distinct();
    }

    public static int dirFileCount(String directoryPath) {
        File directory = new File(directoryPath);
        int fileCount = 0;
        if (directory.exists() && directory.isDirectory()) {
            File[] files = directory.listFiles();

            for (File file : files) {
                if (file.isFile()) {
                    fileCount++;
                }
            }

            System.out.println("Number of files in the directory: " + fileCount);
        }
        return fileCount;
    }

    /**
     * 批量转化sql
     */
    public static void batchExcelToSql() {
        ExcelReader reader = ExcelUtil.getReader("C:\\Users\\yliu\\Desktop\\trans\\病种分析.xlsx");
        List<Map<String, Object>> maps = reader.readAll();
        int count = 0;
        for (Map<String, Object> map : maps) {
            String diseaseName = (String) map.get("疾病");
            readEmpiIdToSql(diseaseName, count);
            count++;
        }
    }

    /**
     * 读取excel转sql
     */
    public static void readEmpiIdToSql(String diseaseName, int count) {
        ExcelReader reader = ExcelUtil.getReader(FileUtil.file(EMPI_ID_EXCEL_FILE_PATH));
        List<Map<String, Object>> readAll = reader.readAll();
        StringBuffer empiIds = new StringBuffer();
        readAll.stream().forEach(element -> {
            if (diseaseName.equals(element.get("name"))) {
                empiIds.append("'").append(element.get("empiid")).append("'").append(",");
            }
        });
        String sql_empiId = empiIds.toString();
        if (empiIds.toString().endsWith(",")) {
            sql_empiId = empiIds.substring(0, empiIds.length() - 1);
        }

        String sql = "select cr.empi_id ,crt.trans_text from call_record cr , call_record_trans crt where call_status = 2 and start_time > '2023-07-01' and cr.id =crt.call_record_id and talk_time_length > 200 and empi_id in (" + sql_empiId + ")";
        System.out.println("================SQL拼接结果==================");
        System.out.println(sql);
        FileWriter fileWriter = new FileWriter("C:\\Users\\yliu\\Desktop\\trans\\sql\\" + count + "_" + diseaseName + ".txt");
        fileWriter.write(sql);
        reader.close();

    }

    /**
     * 读取语音转文字，解析患者
     */
    public static void readTransText() {
        CsvReader reader = CsvUtil.getReader();
        List<TranExcel> tranExcels = reader.read(ResourceUtil.getReader(SQL_FILE_PATH, CharsetUtil.CHARSET_GBK), TranExcel.class);
        int count = 0;
        for (TranExcel tranExcel : tranExcels) {
            List<TranExcel.Tran> trans = JSON.parseArray(tranExcel.getTrans_text(), TranExcel.Tran.class);
            trans.removeIf(transText -> ("个案师".equals(transText.getSpeaker()) || "A".equals(transText.getSpeaker())));
            StringBuffer speakerText = new StringBuffer();
            trans.forEach(tran -> {
                speakerText.append(tran.getText()).append(",");
            });
            System.out.println(speakerText);
            FileWriter fileWriter = new FileWriter(BASE_PATH + "tran\\" + TRAN_FILE + count + ".txt");
            fileWriter.write(speakerText.toString());
            count++;
        }

    }

    /**
     * gpt接口
     *
     * @param content
     * @return
     */
    public static String openAi(String content) {
        String url = "https://jianhai.openai.azure.com/openai/deployments/jianhaiGPT/chat/completions?api-version=2023-05-15";
        OpenAiRes openAiRes = new OpenAiRes();
        OpenAiRes.MessagesDTO messagesDTO = new OpenAiRes.MessagesDTO();
        messagesDTO.setContent(content);
        List<OpenAiRes.MessagesDTO> messagesDTOS = new ArrayList<>();
        messagesDTOS.add(messagesDTO);
        openAiRes.setMessages(messagesDTOS);
        String body = JSON.toJSONString(openAiRes);
        String result = "";
        try {
            String respOpenAi = HttpRequest.post(url)
                    .body(body)
                    .header("api-key", "0fdb7abba33645e3b39a7e0f53d98fa6")
                    .timeout(300000)
                    .execute().body();
            OpenAiResp openAiResp = JSON.parseObject(respOpenAi, OpenAiResp.class);
            System.out.println("【OpenAI】:" + JSONObject.toJSONString(respOpenAi));
            result = openAiResp.getChoices().get(0).getMessage().getContent();
            System.out.println("【OpenAi结果返回】" + result);
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("结果报错，直接跳过");
        }
        return result;
    }

    public static void readPatCallText() {
        try {
            int count = 0;
            while (true) {
                FileReader fileReader = null;
                try {
                    fileReader = new FileReader(BASE_PATH + "tran\\" + TRAN_FILE + count + ".txt");
                } catch (Exception e) {
                    System.out.println("文件读取结束");
                    break;
                }
                FileReader finalFileReader = fileReader;
                int finalCount = count;
                executor.execute(() -> {
                    String result = templateA(finalFileReader.readString(), DISEASE_NAME);
                    FileWriter fileWriter = new FileWriter(BASE_PATH + "openaiResult\\" + DISEASE_NAME + "-result" + finalCount + ".txt");
                    fileWriter.write(result);
                });
                count++;
            }
            System.out.println("程序执行完成");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }

    }


    /**
     * @param content 录音内容
     * @param disease 病种
     * @return
     */
    public static String templateA(String content, String disease) {
        String template = "下面是一段关于【{}】患者接到随访电话时候表述的内容： {} 现在我希望你仅仅根据患者表述的内容，总结提炼出患者问的与【{}】治疗或康复相关的问题，针对每一个问题，从下面3种格式中任选一种：患者询问某一症状的原因、患者担心某些事情、患者咨询某些事情。直接返回你提炼出来的问题";
        String format = StrUtil.format(template, disease, content, disease);
        return openAi(format);
    }

    /**
     * 提炼患者问题
     *
     * @param content 所有患者问题
     * @return
     */
    public static String templateB(String content, String disease) {
        String template = "下面这些是关于【{}】不同患者提出的所有问题:【{}】；你需要提炼出这些问题中常问的问题";
        String format = StrUtil.format(template, disease, content);
        return openAi(format);
    }

    public static String templateC(String content, String disease) {
//        String template = "下面这些是关于【{}】不同患者总结的高频问题:【{}】；你需要统计各类问题占比后，将相似问题去重后重新给我，我需要你将这些问题描述详细，并给出详细的处理方案，还有这些问题的扩展的解答，你必须按照【高频问题】、【提问占比】、【处理方法】、【扩展】这样的格式给我";
        String template = "下面这些是关于【{}】不同患者总结的高频问题:【{}】；将相似问题去重后重新给我，我需要你将这些问题描述详细，并给出详细的处理方案，还有这些问题的扩展的解答，你必须按照【高频问题】、【处理方法】、【扩展】这样的格式给我";
        String format = StrUtil.format(template, disease, content);
        return openAi(format);
    }

    public static String templateD(String content, String disease) {
        String template = "下面这些是关于【{}】不同患者总结的高频问题以及处理方法:【{}】；将相似问题去掉重新整理，我需要你将这些问题描述详细，并给出详细的处理方案，还有这些问题的扩展的解答，你必须按照【高频问题】、【处理方法】、【扩展】这样的格式给我";
        String format = StrUtil.format(template, disease, content);
        return openAi(format);
    }


    public static void readDiseaseTxtToHighProblems() {
        int totalFiles = dirFileCount(BASE_PATH + "openaiResult\\");
        int numBatches = (totalFiles / 100) + 1;
        int filesPerBatch = totalFiles / numBatches;
        int remainingFiles = totalFiles % numBatches;
        for (int batch = 0; batch <= numBatches; batch++) {
            int filesInThisBatch = filesPerBatch;
            if (remainingFiles > 0) {
                filesInThisBatch++;
                remainingFiles--;
            }
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < filesInThisBatch; i++) {
                int fileIndex = batch * filesPerBatch + i;
                try {
                    FileReader fileReader = new FileReader(BASE_PATH + "openaiResult\\" + DISEASE_NAME + "-result" + fileIndex + ".txt");
                    stringBuilder.append(fileReader.readString());
                } catch (Exception e) {
                    System.err.println("文件不存在跳过");
                }
            }

            System.out.println("患者问题：" + stringBuilder);
            String result = templateB(stringBuilder.toString(), DISEASE_NAME);
            System.out.println("【OpenAI----templateB返回结果】" + result);

            // 将结果写入文件
            String resultFilePath = BASE_PATH + "openaiResult\\templateB\\result_batch" + batch + ".txt";
            FileWriter fileWriter = new FileWriter(resultFilePath);
            fileWriter.write(result);

            // 清空StringBuilder，为下一个循环批次做准备
            stringBuilder.setLength(0);
        }

    }


    public static void distinct() {
        int numBatches = dirFileCount(BASE_PATH + "openaiResult\\templateB\\");
        StringBuilder stringBuilder = new StringBuilder();
        int count = 0;
        while (count < numBatches) {
            FileReader fileReader = new FileReader(BASE_PATH + "openaiResult\\templateB\\result_batch" + count + ".txt");
            count++;
            stringBuilder.append(fileReader.readString());
        }
        System.out.println(stringBuilder);
        String result = templateC(stringBuilder.toString(), DISEASE_NAME);
        System.out.println("【OpenAI----templateC返回结果】" + result);
        FileWriter fileWriter = new FileWriter(BASE_PATH + "openaiResult\\templateC\\result.txt");
        fileWriter.write(result);
    }


}
